home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / connection.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  5.7 KB  |  249 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: connection.c,v 5.2 1992/11/10 08:18:25 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <syslog.h>
  13.  
  14. #include "fsma.h"
  15. #include "sio.h"
  16.  
  17. #include "connection.h"
  18. #include "state.h"
  19.  
  20. static fsma_h connection_allocator ;
  21.  
  22. char *inet_ntoa() ;
  23.  
  24. void msg() ;
  25. void out_of_memory() ;
  26.  
  27.  
  28. status_e conn_init()
  29. {
  30.     int flags = FSM_RETURN_ERROR ;
  31.  
  32. #ifdef DEBUG
  33.     flags |= FSM_ZERO_FREE ;
  34. #endif
  35.     connection_allocator = fsm_create( sizeof( connection_s ), 0, flags ) ;
  36.     return( ( connection_allocator == NULL ) ? FAILED : OK ) ;
  37. }
  38.  
  39.  
  40. /*
  41.  * Get a connection for the specified service and return a pointer
  42.  * to a new struct connection
  43.  */
  44. connection_s *conn_new( sp )
  45.     struct service *sp ;
  46. {
  47.     connection_s new_conn ;
  48.     register connection_s *cp ;
  49.     char *func = "conn_new" ;
  50.     status_e get_connection() ;
  51.  
  52.     CLEAR( new_conn ) ;
  53.  
  54.     /*
  55.      * The reason we first get the connection and then allocate a 
  56.      * struct connection is because we want to always consume some
  57.      * input.
  58.      */
  59.     if ( get_connection( sp, &new_conn ) == FAILED )
  60.         return( NULL ) ;
  61.  
  62.     new_conn.state = CONN_OPEN ;
  63.     new_conn.sp = sp ;
  64.     SVC_HOLD( sp ) ;
  65.  
  66.     cp = COP( fsm_alloc( connection_allocator ) ) ;
  67.     if ( cp == NULL )
  68.     {
  69.         out_of_memory( func ) ;
  70.         conn_cleanup( &new_conn ) ;
  71.         conn_shutdown( &new_conn ) ;
  72.         conn_free( &new_conn ) ;
  73.         return( NULL ) ;
  74.     }
  75.     *cp = new_conn ;
  76.     return( cp ) ;
  77. }
  78.  
  79.  
  80. PRIVATE status_e get_connection( sp, cp )
  81.     struct service *sp ;
  82.     register connection_s *cp ;
  83. {
  84.     int sin_len = sizeof( cp->remote_address ) ;
  85.     register struct service_config *scp = CONF( sp ) ;
  86.     char *func = "get_connection" ;
  87.  
  88.     if ( ACCEPTS_CONNECTIONS( scp ) )
  89.     {
  90.         cp->descriptor = accept( SVC_FD( sp ),
  91.                                                 SA( &cp->remote_address ), &sin_len ) ;
  92.         if ( cp->descriptor == -1 )
  93.         {
  94.             msg( LOG_ERR, func, "service %s, accept: %m", scp->id ) ;
  95.             return( FAILED ) ;
  96.         }
  97.         M_SET( cp->flags, COF_HAVE_ADDRESS ) ;
  98.         M_SET( cp->flags, COF_NEW_DESCRIPTOR ) ;
  99.     }
  100.     else
  101.     {
  102.         if ( scp->socket_type == SOCK_DGRAM )
  103.         {
  104.             char t_ch ;
  105.  
  106.             /*
  107.              * This trick is done to get the remote address.
  108.              * select(2) guaranteed that we won't block on the recvfrom
  109.              */
  110.             if ( recvfrom( SVC_FD( sp ), &t_ch, 1, MSG_PEEK,
  111.                                             SA( &cp->remote_address ), &sin_len ) == -1 )
  112.             {
  113.                 msg( LOG_ERR, func, "service %s, recvfrom: %m", scp->id ) ;
  114.                 return( FAILED ) ;
  115.             }
  116.             M_SET( cp->flags, COF_HAVE_ADDRESS ) ;
  117.         }
  118.         cp->descriptor = SVC_FD( sp ) ;
  119.     }
  120.     return( OK ) ;
  121. }
  122.  
  123.  
  124. /*
  125.  * Close the connection descriptor if it is a new one
  126.  */
  127. void conn_close( cp )
  128.     register connection_s *cp ;
  129. {
  130.     if ( cp->state == CONN_OPEN && M_IS_SET( cp->flags, COF_NEW_DESCRIPTOR ) )
  131.     {
  132.         (void) close( cp->descriptor ) ;
  133.         cp->state = CONN_CLOSED ;
  134.     }
  135. }
  136.  
  137.  
  138. /*
  139.  * Release the specified connection.
  140.  * Certain actions may be performed before doing this:
  141.  *        - invocation of the service shutdown function
  142.  *        - drain of a single UDP packet if the socket type is SOCK_DGRAM
  143.  */
  144. void conn_free( cp )
  145.     register connection_s *cp ;
  146. {
  147.     register struct service *sp = cp->sp ;
  148.     void drain() ;
  149.  
  150.     if ( cp->state == CONN_OPEN )
  151.     {
  152.         if ( M_IS_SET( cp->flags, COF_SHUTDOWN ) )
  153.             svc_shutdown( sp, cp ) ;
  154.         
  155.         if ( M_IS_SET( cp->flags, COF_CLEANUP ) && 
  156.                                     CONF( cp->sp )->socket_type == SOCK_DGRAM )
  157.             drain( cp->descriptor ) ;
  158.     }
  159.  
  160.     if ( SVC_RELE( sp ) == 0 )
  161.         pset_remove( SERVICES( ps ), sp ) ;
  162.  
  163.     conn_close( cp ) ;
  164.  
  165.     fsm_free( connection_allocator, (char *)cp ) ;
  166. }
  167.  
  168.  
  169. /*
  170.  * Since at present only special services are added as alternatives
  171.  * we do not increase the reference count on alternative services.
  172.  */
  173. status_e conn_add_alternative( cp, sp )
  174.     register connection_s *cp ;
  175.     struct service *sp ;
  176. {
  177.     char *func = "conn_add_alternative" ;
  178.  
  179.     if ( sp == NULL )
  180.         return( FAILED ) ;
  181.  
  182.     if ( cp->alternative_count >= MAX_ALTERNATIVES )
  183.     {
  184.         msg( LOG_ERR, func,
  185.             "Cannot add alternative service %s to connection for service %s",
  186.                 CONF( sp )->id, CONF( cp->sp )->id ) ;
  187.         return( FAILED ) ;
  188.     }
  189.  
  190.     if ( debug.on )
  191.         msg( LOG_DEBUG, func,
  192.             "Adding alternative service %s to connection of service %s",
  193.                 CONF( sp )->id, CONF( cp->sp )->id ) ;
  194.  
  195.     cp->alternatives[ cp->alternative_count++ ] = sp ;
  196.     return( OK ) ;
  197. }
  198.  
  199.  
  200. /*
  201.  * Start invoking alternative services starting from the next alternative one
  202.  * until either we get a successful invocation or we run out of services
  203.  */
  204. status_e conn_start_alternative( cp )
  205.     register connection_s *cp ;
  206. {
  207.     char *func = "conn_start_alternative" ;
  208.  
  209.     while ( cp->next_alternative < cp->alternative_count )
  210.     {
  211.         struct service *asp = cp->alternatives[ cp->next_alternative++ ] ;
  212.         
  213.         if ( SVC_HANDLE( asp, cp ) == OK )
  214.         {
  215.             if ( debug.on )
  216.                 msg( LOG_DEBUG, func,
  217.                     "Started alternative service %s", CONF( asp )->id ) ;
  218.             return( OK ) ;
  219.         }
  220.     }
  221.     return( FAILED ) ;
  222. }
  223.  
  224.  
  225. void conn_dump( cp, fd )
  226.     connection_s *cp ;
  227.     int fd ;
  228. {
  229.     unsigned u ;
  230.     void tabprint() ;
  231.  
  232.     tabprint( fd, 1, "state = %s\n",
  233.             ( cp->state == CONN_CLOSED ) ? "CLOSED" : "OPEN" ) ;
  234.     tabprint( fd, 1, "service = %s\n", CONF( cp->sp )->id ) ;
  235.     tabprint( fd, 1, "descriptor = %d\n", cp->descriptor ) ;
  236.     tabprint( fd, 1, "flags = %#x\n", cp->flags ) ;
  237.     tabprint( fd, 1, "remote_address = %s,%d\n",
  238.                                         inet_ntoa( cp->remote_address.sin_addr ),
  239.                                         ntohs( cp->remote_address.sin_port ) ) ;
  240.     tabprint( fd, 1, "Alternative services = " ) ;
  241.     for ( u = 0 ; u < cp->alternative_count ; u++ )
  242.         Sprint( fd, " %s", CONF( cp->alternatives[ u ] )->id ) ;
  243.     Sputchar( fd, '\n' ) ;
  244.     if ( cp->alternative_count > 0 )
  245.         tabprint( fd, 1, "next alternative service = %s\n",
  246.                 CONF( cp->alternatives[ cp->next_alternative ] )->id ) ;
  247. }
  248.  
  249.